# 导入模块
import requests
from lxml import etree
import csv

# 请求头信息
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}

# 初始化电影信息列表，用于存储爬取到的所有电影数据
moive_list = []

# 循环爬取前11页的电影数据（豆瓣电影Top250每页显示25条，共10页，但这里设置为12以确保覆盖）
for page in range(1, 12):
    # 构建当前页的URL，每页25条记录，通过start参数控制偏移量
    url = f'https://movie.douban.com/top250?start={(page - 1) * 25}&filter='
    # 发送HTTP GET请求获取页面内容
    res = requests.get(url, headers=headers)
    # 获取响应的文本内容
    html = res.text
    # 将HTML文本解析为XPath可操作的Element对象
    tree = etree.HTML(html)

    # 使用XPath选择所有电影信息所在的div元素（class为info的div）
    divs = tree.xpath('//div[@class="info"]')

    # 遍历每个电影信息div
    for div in divs:
        # 初始化字典，用于存储单个电影的所有信息
        dic = {}
        # 获取电影中文名（可能包含别名，需进一步处理）
        title = div.xpath('./div[@class="hd"]/a/span[@class="title"]/text()')
        # 处理中文名，去除可能存在的别名分隔符
        title_cn = ''.join(title).split('\xa0/\xa0')[0]
        # 将中文名存入字典
        dic['电影中文名'] = title_cn

        # 获取电影英文名（处理掉前面的分隔符）
        title_en = div.xpath('./div[@class="hd"]/a/span[2]/text()')[0].strip('\xa0/\xa0')
        dic['电影英文名'] = title_en # 将英文名存入字典

        # 获取电影详情页链接
        links = div.xpath('./div[@class="hd"]/a/@href')[0]
        dic['电影详情页链接'] = links  # 将链接存入字典

        # 从描述文本中提取导演信息（通过分割字符串）
        director = div.xpath('./div[@class="bd"]/p/text()')[0].strip().split('导演: ')[1].split('主演: ')[0]
        dic['导演'] = director  # 将导演信息存入字典

        # 尝试提取主演信息，可能不存在，使用try-except处理异常
        try:
            act = div.xpath('./div[@class="bd"]/p/text()')[0].strip().split('导演: ')[1].split('主演: ')[1]
        except IndexError: # 若不存在主演信息，设为空字符串
            act = ''
        dic['主演'] = act # 将主演信息存入字典

        # 从描述文本中提取上映年份、国籍和类型信息
        info_parts = div.xpath('./div[@class="bd"]/p/text()')[1].strip().split('/')
        dic['上映年份'] = info_parts[0].strip()

        # 根据文本特征判断国籍和类型的位置（处理不同格式的文本）
        if len(info_parts[1].strip()[0].encode('utf-8')) == 1:
            # 处理特殊情况（如年份后直接跟类型）
            dic['国籍'] = info_parts[2].strip()
            dic['类型'] = info_parts[3].strip()
        else:
            dic['国籍'] = info_parts[1].strip()
            dic['类型'] = info_parts[2].strip()
        # 提取电影评分
        dic['评分'] = div.xpath('./div[@class="bd"]/div/span[2]/text()')[0]
        # 提取评分人数
        dic['评分人数'] = div.xpath('./div[@class="bd"]/div/span[4]/text()')[0]

        # 将当前电影的所有信息添加到电影列表中
        moive_list.append(dic)
    # 打印当前页爬取完成的提示信息
    print(f'----------------------第{page}页爬取完成--------------------------------------')

print('-----------------------爬虫结束-------------------------------')

# 定义CSV文件的列名（表头）
fieldnames = [
    '电影中文名', '电影英文名', '电影详情页链接', '导演',
    '主演', '上映年份', '国籍', '类型', '评分', '评分人数'
]

# 保存爬取的数据到CSV文件
# 保存数据
with open('豆瓣电影Top250.csv', 'w', encoding='utf-8-sig', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(moive_list)
